/**
 * Copyright (c) [2025] [AGIROS] 
 * [travoddsgen] is licensed under Mulan PSL v2. 
 * You can use this software according to the terms and conditions of the Mulan PSL v2. 
 * You may obtain a copy of Mulan PSL v2 at: 
 *          http://license.coscl.org.cn/MulanPSL2 
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
 * See the Mulan PSL v2 for more details.
 */ 

#include "CppLangTypeHeaderVisitor.h"
#include <fstream>

CppLangTypeHeaderVisitor::CppLangTypeHeaderVisitor(
    const std::string& outputDir, 
    const std::string& fileName, 
    CppLangTypeNameVisitor* typeNameVisitor)
    : FileGenVisitor(outputDir, fileName),
      typeNameVisitor_(typeNameVisitor) {
}

void CppLangTypeHeaderVisitor::visit(SpecificationNode& node) {
    // 从文件名中提取不带后缀的文件名
    std::string fileName = fileName_.substr(0, fileName_.find_last_of("."));
    // 文件头的宏声明
    std::string headerGuard = "#ifndef " + fileName + "_H\n";
    headerGuard += "#define " + fileName + "_H\n";
    content_ += headerGuard + "\n";

    // 头文件包含
    std::string includes = "";
    includes += "#include <string>\n";
    includes += "#include <vector>\n";
    includes += "#include <map>\n";
    includes += "#include <cstdint>\n";
    includes += "#include \"cdr/agicdr.h\"\n";
    includes += "\n";
    content_ += includes;

    // DLL导出宏定义
    std::string dllExportMacro = "";
    dllExportMacro += "#if defined(DDS_TYPE_EXPORT) && defined(_WIN32)\n";
    dllExportMacro += "#define DDS_TYPE_API __declspec(dllexport)\n";
    dllExportMacro += "#else\n";
    dllExportMacro += "#define DDS_TYPE_API \n";
    dllExportMacro += "#endif\n";
    content_ += dllExportMacro + "\n";

    // __cplusplus宏定义开始
    content_ += "#ifdef __cplusplus\n";
    content_ += "extern \"C\" {\n";
    content_ += "#endif\n\n";

    // 前置声明
    const std::map<std::string, std::string>& forwardDeclare = typeNameVisitor_->getForwardDeclare();
    for (auto& pair : forwardDeclare) {
        std::string forwardDeclareName = pair.first;
        // 在forwardDeclareName中循环查找::并转化为namespace声明
        std::size_t index = forwardDeclareName.find("::");
        std::string namespaceHeader = "";
        std::string namespaceTail = "";
        while (index != std::string::npos) {
            namespaceHeader += "namespace " + forwardDeclareName.substr(0, index) + " { ";
            namespaceTail += "} ";
            forwardDeclareName = forwardDeclareName.substr(index + 2);
            index = forwardDeclareName.find("::");
        }
        content_ += namespaceHeader + pair.second + " " + forwardDeclareName + "; " + namespaceTail + "\n";
        content_ += "\n";
    }
    
    // 递归访问子节点
    if (node.definitions_) {
        node.definitions_->accept(*this);
    }

    // __cplusplus宏定义结尾
    content_ += "#ifdef __cplusplus\n";
    content_ += "}\n";
    content_ += "#endif\n";

    // 文件尾的宏声明
    std::string endGuard = "#endif /* " + fileName + "_H */\n";
    content_ += endGuard;

    // 将_content写入文件
    writeToFile();
}

void CppLangTypeHeaderVisitor::visit(IncludeDclNode& node) {
    // 递归访问子节点
    std::string includedFile = typeNameVisitor_->getIncludedFileName(node);
    content_ += "#include \"" + includedFile + ".h\"\n";
    content_ += "\n";
}

void CppLangTypeHeaderVisitor::visit(ModuleDclNode& node) {
    // namespace开始
    content_ += "namespace " + *node.identifier_ + " {\n\n";
    // 递归访问子节点
    for (auto& def : node.definitions_->nodes_) {
        def->accept(*this);
    }
    // namespace结束
    content_ += "} // namespace " + *node.identifier_ + "\n\n";
}

void CppLangTypeHeaderVisitor::visit(ConstDclNode& node) {
    std::string _constDclContent = "const ";
    // 类型名
    _constDclContent += typeNameVisitor_->findShortName(node.type_);
    // 常量名
    std::string identifier = typeNameVisitor_->findShortName(&node);
    _constDclContent += " " + identifier;
    _constDclContent += " = ";
    // 常量表达式
    _constDclContent += typeNameVisitor_->findName(node.expression_);
    _constDclContent += ";\n\n";
    content_ += _constDclContent;
}

void CppLangTypeHeaderVisitor::visit(StructDefNode& node) {
    // 结构体的Annotation
    if (node.annotations_) {
        for (auto& annotation : node.annotations_->nodes_) {
            content_ += "// @" + annotation->toString() + "\n";
        }
    }
    // 声明模块前缀_结构体名的结构体
    std::string structName = typeNameVisitor_->findShortName(&node);
    std::string structDefHeader = "class DDS_TYPE_API " + structName;
    // 继承
    if (node.parent_) {
        DefinitionNode* parentNode = typeNameVisitor_->findType(node.parent_);
        std::string parentName = typeNameVisitor_->findName(parentNode);
        structDefHeader += " : public " + parentName;
    }
    structDefHeader += " {\n";
    structDefHeader += "public:\n";
    // 定义operator<比较函数
    indentLevel_++;
    structDefHeader += indent() + "bool operator<(const " + structName + "& rhs) const {\n";
    structDefHeader += indent() + "    return false;\n";
    structDefHeader += indent() + "}\n";
    indentLevel_--;

    // 结构体定义开始
    content_ += structDefHeader;
    indentLevel_++;
    // 递归访问子节点
    if (node.members_) {
        node.members_->accept(*this);
    }
    indentLevel_--;
    // 结构体定义结束
    content_ += "};\n\n";
}

void CppLangTypeHeaderVisitor::visit(SwitchTypeSpecNode& node) {
    if (node.type_) {
        std::string typeName = typeNameVisitor_->findName(node.type_);
        content_ += indent() + typeName + " u_;\n";
    } else if (node.scopedName_) {
        DefinitionNode* typeDclNode = typeNameVisitor_->findType(node.scopedName_);
        std::string switchTypeName = typeNameVisitor_->findName(typeDclNode);
        content_ += indent() + switchTypeName + " u_;\n";
    }
}

void CppLangTypeHeaderVisitor::visit(UnionDefNode& node) {
    // 联合的Annotation
    if (node.annotations_) {
        for (auto& annotation : node.annotations_->nodes_) {
            content_ += "// @" + annotation->toString() + "\n";
        }
    }
    // 声明模块前缀_联合名的联合
    std::string unionName = typeNameVisitor_->findShortName(&node);
    std::string unionDefHeader = "class DDS_TYPE_API " + unionName + " {\n";
    unionDefHeader += "public:\n";
    // 联合定义开始
    content_ += unionDefHeader;
    indentLevel_++;
    // switch
    node.switchType_->accept(*this);
    // 递归访问子节点
    if (node.cases_) {
        node.cases_->accept(*this);
    }
    indentLevel_--;
    // 联合定义结束
    content_ += "};\n\n";
}

void CppLangTypeHeaderVisitor::visit(MemberNode& node) {
    std::string annotationStr = "";
    bool isShared = false;
    // 成员的Annotation
    if (node.annotations_) {
        annotationStr += "// ";
        for (auto& annotation : node.annotations_->nodes_) {
            annotationStr += "@" + annotation->toString();
            if (annotation->value_) {
                std::string posIndexStr = typeNameVisitor_->findName(annotation->value_);
                annotationStr += "(" + posIndexStr + ")";
            }
            annotationStr += " ";
            if (annotation->annotation_ == MemberAnnotationNode::AnnotationType::SHARED_ANNOTATION) {
                isShared = true;
            }
        }
    }
    // 成员类型
    if (isShared) {
        content_ += indent() + typeNameVisitor_->findShortName(node.type_) + "*";
    } else {
        content_ += indent() + typeNameVisitor_->findName(node.type_);
    }
    // 成员名
    content_ += " " + *node.identifier_;
    // 成员的数组维度
    if (node.arrayDims_) {
        for (auto& fixedArraySize : node.arrayDims_->nodes_) {
            content_ += typeNameVisitor_->findName(fixedArraySize);
        }
    }
    content_ += ";";
    content_ += annotationStr; 
    content_ += "\n";
}

void CppLangTypeHeaderVisitor::visit(EnumDclNode& node) {
    // 标注
    if (node.annotations_) {
        for (auto& annotation : node.annotations_->nodes_) {
            content_ += "// @" + annotation->toString() + "\n";
        }
    }
    // 枚举定义
    std::string enumName = typeNameVisitor_->findShortName(&node);
    content_ += "enum " + enumName + " {\n";
    // 枚举值
    indentLevel_++;
    if (node.enumerators_) {
        node.enumerators_->accept(*this);
    }
    indentLevel_--;
    // 枚举定义结束
    content_ += "};\n\n";
}

void CppLangTypeHeaderVisitor::visit(EnumeratorNode& node) {
    // 枚举值
    content_ += indent() + *node.identifier_;
    if (node.value_) {
        content_ += " = " + typeNameVisitor_->findName(node.value_);
    }
    content_ += ",\n";
}

void CppLangTypeHeaderVisitor::visit(TypeDefDclNode& node) {
    // 类型定义名
    std::string typeDefName = typeNameVisitor_->findShortName(&node);
    std::string refTypeName = "";
    // 如果是BaseTypeNode
    BaseTypeNode* baseTypeNode = dynamic_cast<BaseTypeNode*>(node.refType_);
    StringTypeNode* stringTypeNode = dynamic_cast<StringTypeNode*>(node.refType_);
    WideStringTypeNode* wstringTypeNode = dynamic_cast<WideStringTypeNode*>(node.refType_);
    if (baseTypeNode) {
        refTypeName = typeNameVisitor_->findName(baseTypeNode);
    } else if (stringTypeNode) {
        refTypeName = typeNameVisitor_->findName(stringTypeNode);
    } else if (wstringTypeNode) {
        refTypeName = typeNameVisitor_->findName(wstringTypeNode);
    } else {
        // scopedName
        ScopedNameNode* scopedNameNode = dynamic_cast<ScopedNameNode*>(node.refType_);
        if (scopedNameNode) {
            refTypeName = typeNameVisitor_->findName(scopedNameNode);
        } else {
            // 报错
            std::cerr << "Error: unknown typedef ref type " << *node.identifier_ << std::endl;
            exit(1);
        }
    }
    content_ += "typedef " + refTypeName + " " + typeDefName;
    // 数组维度
    if (node.dims_) {
        for (auto& fixedArraySize : node.dims_->nodes_) {
            content_ += typeNameVisitor_->findName(fixedArraySize);
        }
    }
    content_ += ";\n\n";
}
